package basedao

import (
	"context"
	"fmt"
	"reflect"

	"gorm.io/gorm/clause"
)

func (b *BaseDao) InsertOneRecord(ctx context.Context) error {
	db := b.Db.WithContext(ctx).Table(b.TableName).Create(b.Model)
	if db.Error != nil {
		return db.Error
	}

	return nil
}

func (b *BaseDao) InsertBatch(ctx context.Context, batch interface{}, batchSize int) error {
	db := b.Db.WithContext(ctx).Clauses(clause.OnConflict{
		UpdateAll: true,
	}).Table(b.TableName).CreateInBatches(batch, batchSize)
	if db.Error != nil {
		return db.Error
	}

	return nil
}

func (b *BaseDao) GetById(ctx context.Context, id uint64, res interface{}) error {
	db := b.Db.WithContext(ctx).Table(b.TableName).Where("id = (?)", id).
		Where("deleted = ?", 0).First(res)
	if db.Error != nil {
		return db.Error
	}

	return nil
}

func (b *BaseDao) GetsByCond(ctx context.Context, cond map[string]interface{}, res interface{}) error {
	db := b.Db.WithContext(ctx).Table(b.TableName)

	for k, v := range cond {
		switch k {
		case "limit":
			db = db.Limit(v.(int)).Order("ID DESC")
		case "offset":
			db = db.Offset(v.(int))
		case "description":
			db = db.Where(k+" like ?", fmt.Sprintf("%v%v%v", "%", v, "%"))
		case "update_time":
			db = db.Where(k+" >= (?)", v)
		case "update_time <=":
			db = db.Where("update_time <= (?)", v)
		default:
			switch reflect.TypeOf(v).Kind() {
			case reflect.Array, reflect.Slice:
				db = db.Where(k+" in (?)", v)
			default:
				db = db.Where(k+" = ?", v)
			}
		}
	}

	db = db.Find(res)
	if db.Error != nil {
		return db.Error
	}

	return nil
}

func (b *BaseDao) UpdateById(ctx context.Context, id uint64, update map[string]interface{}) (int64, error) {
	db := b.Db.WithContext(ctx).Table(b.TableName).Where("id = (?)", id).
		Updates(update)
	if db.Error != nil {
		return 0, db.Error
	}

	return db.RowsAffected, nil
}

func (b *BaseDao) GetTotalCount(ctx context.Context, cond map[string]interface{}, count *int64) error {
	db := b.Db.WithContext(ctx).Table(b.TableName)
	for k, v := range cond {
		switch k {
		case "limit", "offset":
			continue
		case "description":
			db = db.Where(k+" like ?", fmt.Sprintf("%v%v%v", "%", v, "%"))
		default:
			switch reflect.TypeOf(v).Kind() {
			case reflect.Array, reflect.Slice:
				db = db.Where(k+" in (?)", v)
			default:
				db = db.Where(k+" = ?", v)
			}
		}
	}

	db = db.Count(count)
	if db.Error != nil {
		return db.Error
	}

	return nil
}
